package com.hardydou.framework.log;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.hardydou.common.utils.RegionUtil;
import com.hardydou.framework.log.anno.LogMetaInfo;
import com.hardydou.system.model.LoginUserDetails;
import com.hardydou.system.model.SystemOperLog;
import com.hardydou.system.service.ISystemDeptService;
import com.hardydou.system.service.ISystemLoginLogService;
import com.hardydou.system.service.ISystemOperLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author ：hardy
 * @description：记录 操作日志
 * @date ：Created in 2020/5/31
 * @Copyright ：Hardydou.com
 */
@Aspect
@Component
public class LogAspect {

    final static Log logger = LogFactory.get();

    @Autowired
    private ISystemDeptService deptService;

    @Autowired
    private ISystemOperLogService operLogService;

    @Autowired
    private ISystemLoginLogService loginLogService;

    /**
     * 增加日志切入点
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)||@annotation(org.springframework.web.bind.annotation.DeleteMapping)||@annotation(org.springframework.web.bind.annotation.PutMapping)")
    public void operLogPointCut() {
    }

    @AfterReturning(pointcut = "operLogPointCut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        SystemOperLog log = createOperLog(joinPoint);
        log.setFail(false);
        log.setResult(JSONUtil.toJsonStr(result));
        operLogService.add(log);
    }

    @AfterThrowing(value = "operLogPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        SystemOperLog log = createOperLog(joinPoint);
        log.setFail(true);
        log.setResult(e.getMessage());
        operLogService.add(log);
    }

    protected SystemOperLog createOperLog(JoinPoint joinPoint) {
        SystemOperLog systemOperLog = new SystemOperLog();
        // 请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        systemOperLog.setReqUrl(request.getRequestURI());
        systemOperLog.setReqMethod(request.getMethod());
        String ip = ServletUtil.getClientIP(request);
        systemOperLog.setReqIp(ip);
        systemOperLog.setReqLocation(RegionUtil.getRegion(ip));
        systemOperLog.setReqParam(JSONUtil.toJsonStr(ServletUtil.getParamMap(request)));
        // 处理端信息
        LogMetaInfo operLog = joinPoint.getTarget().getClass().getAnnotation(LogMetaInfo.class);
        if (operLog != null) {
            systemOperLog.setModule(operLog.module());
        }
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        systemOperLog.setHandleMethod(className + "." + methodName + "()");
        //用户信息
        LoginUserDetails user = (LoginUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (user != null) {
            systemOperLog.setUserId(user.getSystemUser().getUserId());
            systemOperLog.setUserName(user.getSystemUser().getUsername());
        }
        return systemOperLog;
    }
}
